package com.bosicloud.cmb.ibp;

import com.alibaba.fastjson.JSON;
import com.bosicloud.cmb.ibp.commom.constant.IbpError;
import com.bosicloud.cmb.ibp.commom.dto.UnionResult;
import com.bosicloud.cmb.ibp.commom.exception.BusinessException;
import com.bosicloud.cmb.ibp.commom.exception.RemoteMethodArgumentException;
import com.bosicloud.cmb.ibp.commom.exception.UnknowException;
import feign.Response;
import feign.Util;
import feign.codec.ErrorDecoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;

/**
 * @author Jack Peng / ziliang.peng@bosicloud.com
 */
@ConditionalOnClass(ErrorDecoder.class)
@Configuration
@Slf4j
@SuppressWarnings("ALL")
public class FeignErrorDecoder implements ErrorDecoder {

    private final ErrorDecoder defaultErrorDecoder = new Default();

    @Override
    public Exception decode(String methodKey, Response response) {

        try {

            String message = Util.toString(response.body().asReader());

            UnionResult urException = JSON.parseObject(message, UnionResult.class);

            log.debug("解码异常信息.\n", JSON.toJSONString(urException, true));

            if(urException.getStatus() == UnionResult.StatusEnum.Fail.code()) {
                return new BusinessException(urException.getMsg());
            }

            if(urException.getStatus() == UnionResult.StatusEnum.FormFail.code()) {
                return RemoteMethodArgumentException.builder().data(urException.getData()).build();
            }

            if(urException.getStatus() == UnionResult.StatusEnum.InnerError.code()) {
                return new BusinessException(urException.getMsg());
            }

            return UnknowException.builder().msg(urException.getMsg()).data(urException.getData()).build();

        } catch (Exception ignored) {
            log.error("远程调用错误解码IO异常.", ignored);
        }

        return defaultErrorDecoder.decode(methodKey, response);
    }
}
